package com.ecarx.vhaltests.hy11.testcases.system.windowdoorlock;

import static android.car.VehiclePropertyIds.DOOR_POS;

import android.car.VehicleAreaDoor;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.CarPropertyManager;
import android.util.Log;

import com.ecarx.vhaltests.IpcpClient;
import com.ecarx.vhaltests.VehicleConstants;
import com.ecarx.vhaltests.VhalUnitTestBase;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import vendor.ecarx.xma.automotive.vehicle.V2_0.ECarXVehicleProperty;

/**
 * [SW_FC_009_035] Vehicle 两盖-电动尾门实时位置
 */
public class DoorPosTest extends VhalUnitTestBase {
    private static final String TAG = "DoorPosTest";
    private static int cbValue;
    private static int cbStatus;

    final static Object mLock = new Object();
    private static final IpcpClient ipcpClient = new IpcpClient();

    @BeforeClass
    public static void testInit() {
        mCarPropertyMgr.registerCallback(carPropertyEventCallback, DOOR_POS, CarPropertyManager.SENSOR_RATE_ONCHANGE);
        setConfig();
    }

    @Test
    public void test001_DoorPosAvail() {
        setDoorPosAvail();
        lockWait();
        Assert.assertEquals(cbStatus, CarPropertyValue.STATUS_AVAILABLE);
        testDoorPosIsAvail();
    }
    @Test
    public void test002_DoorPosNotAvail() {
        setDoorPosNotAvail();
        lockWait();
        Assert.assertEquals(cbStatus, CarPropertyValue.STATUS_UNAVAILABLE);
        testDoorPosNotAvail();
    }

    /**
     * set value between 96-100
     */
    @Test
    public void test003_DoorPosSet01() {
        setDoorPosAvail();
        setDoorPosValue(100);
        lockWait();
        Assert.assertEquals(95, cbValue);
        Assert.assertEquals(CarPropertyValue.STATUS_AVAILABLE, cbStatus);
        testDoorPosValue(VehicleAreaDoor.DOOR_REAR, 95);

        boolean sts = mCarPropertyMgr.getBooleanProperty(ECarXVehicleProperty.DOOR_MOVING_STATE, VehicleAreaDoor.DOOR_REAR);
        Assert.assertTrue(sts);
        delay(2000);
        sts = mCarPropertyMgr.getBooleanProperty(ECarXVehicleProperty.DOOR_MOVING_STATE, VehicleAreaDoor.DOOR_REAR);
        Assert.assertFalse(sts);
    }

    /**
     * set value between 11-95
     */
    @Test
    public void test004_DoorPosSet02() {
        setDoorPosAvail();
        setDoorPosValue(50);
        lockWait();
        Assert.assertEquals(50, cbValue);
        Assert.assertEquals(CarPropertyValue.STATUS_AVAILABLE, cbStatus);
        testDoorPosValue(VehicleAreaDoor.DOOR_REAR, 50);

        delay();
        setDoorPosValue(52);
        delay();
        testDoorPosValue(VehicleAreaDoor.DOOR_REAR, 50);
    }

    /**
     * set value between 0-10
     */
    @Test
    public void test005_DoorPosSet03() {
        setDoorPosAvail();
        setDoorPosValue(5);
        lockWait();
        Assert.assertEquals(0, cbValue);
        Assert.assertEquals(CarPropertyValue.STATUS_AVAILABLE, cbStatus);
        testDoorPosValue(VehicleAreaDoor.DOOR_REAR, 0);
    }

    public void testDoorPosValue(int areaId, int value) {
        int halValue = mCarPropertyMgr.getIntProperty(DOOR_POS, areaId);
        Assert.assertEquals(value, halValue);
    }

    public void setDoorPosValue( int value) {
        mCarPropertyMgr.setIntProperty(DOOR_POS, VehicleAreaDoor.DOOR_REAR, value);
    }

    public void testDoorPosIsAvail() {
        boolean isAvail = mCarPropertyMgr.isPropertyAvailable(DOOR_POS, VehicleAreaDoor.DOOR_REAR);
        Assert.assertTrue(isAvail);
    }


    public void testDoorPosNotAvail() {
        boolean isAvail = mCarPropertyMgr.isPropertyAvailable(DOOR_POS, VehicleAreaDoor.DOOR_REAR);
        Assert.assertFalse(isAvail);
    }


    public void lockWait() {
        try {
            synchronized (mLock) {
                mLock.wait(1000);
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static CarPropertyManager.CarPropertyEventCallback carPropertyEventCallback = new CarPropertyManager.CarPropertyEventCallback() {
        @Override
        public void onChangeEvent(CarPropertyValue carPropertyValue) {
            try {
                Log.d(TAG, "DOOR_POS onChangeEvent value:propertyId" + carPropertyValue.getPropertyId() + ",value:" + carPropertyValue.getValue());
                Log.d(TAG, "DOOR_POS onChangeEvent Status" + carPropertyValue.getStatus());
                Log.d(TAG, "DOOR_POS onChangeEvent areaId" + carPropertyValue.getAreaId());

                cbValue = (int) carPropertyValue.getValue();
                cbStatus = carPropertyValue.getStatus();
                Log.d(TAG, "DOOR_POS onChangeEvent halValueTop2：" + cbValue);
                synchronized (mLock) {
                    mLock.notify();
                }

            } catch (Exception e) {
                Log.e(TAG, e.getMessage());
            }
        }

        @Override
        public void onErrorEvent(int i, int i1) {

        }
    };

    public void setDoorPosAvail() {
        setCarConfig(2);
        setCEM(VehicleConstants.CAR_MODE_NOMAL, VehicleConstants.USG_MODE_DRIVING);
        delay();
    }

    public void setDoorPosNotAvail() {
        setCarConfig(2);
        setCEM(VehicleConstants.CAR_MODE_CRASH,VehicleConstants.USG_MODE_ABANDON);
        delay();
    }

    private static void setConfig() {
        // HY11 car mode & usage mode 信号对应 ECU 为 CEM
        int cemSvcId = 37;
        int[] cemOperIds = {999};
        // carconfig 对应 Service ID & Operation ID
        int ccSvcId = 135;
        int[] ccOperIds = {200};

        boolean retCem = ipcpClient.setConfig(cemSvcId, cemOperIds);
        Assert.assertTrue(retCem);

        boolean retCc = ipcpClient.setConfig(ccSvcId, ccOperIds);
        Assert.assertTrue(retCc);
    }

    public void setCEM(int carMode, int usgMode) {
        int cemSvcId = 37;
        int cemOperId = 999;
        String[] cems = {"vehModMngtGlbSafe1CarModSts1","vehModMngtGlbSafe1UsgModSts"};
        int[] cemValues = {carMode, usgMode};
        boolean cemResult = ipcpClient.setCEMSignal(cemSvcId, cemOperId, cems, cemValues);
        Assert.assertTrue(cemResult);
        delay();
    }

    public void setCarConfig(int carConfigValue) {
        int ccSvcId = 135;
        int ccOperId = 200;
        int[] configs = {98};
        int[] values = {carConfigValue};
        boolean ccResult = ipcpClient.setCarconfigSignal(ccSvcId, ccOperId, configs, values);
        Assert.assertTrue(ccResult);
        delay();
    }
}
